﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using Medianamik.Core;
using Medianamik.Core.Action;
using Medianamik.Core.Configuration;
using Medianamik.Core.Urls;

namespace Medianamik.UI.Controls
{
    public class UrlActionHandler : IActionHandler
    {
        public static readonly MedianamikConfigSection MedianamikConfigSection =
            (MedianamikConfigSection)ConfigurationManager.GetSection(ConfigurationSectionName.MEDIANAMIK);

        public void Initialize(ActionManager events)
        {
            events.BeforeCreateNodeInstance += BeforeSaveNodeInstance;
            events.BeforeUpdateNodeInstance += BeforeSaveNodeInstance;
        }

        public virtual void BeforeSaveNodeInstance(ActionEventArgs<NodeInstance> args)
        {
            Node node = null;

            if (args.Item.HasUrl && args.Item.Culture.Name != String.Empty)
            {
                if (args.Item.Node != null)
                {
                    var urlProp = args.Item.Properties["url"];

                    if (string.IsNullOrEmpty(urlProp.GetValue<string>()) ||
                        XDocument.Parse(urlProp.GetValue<string>()).Descendants("url").Count() == 0)
                    {
                        if (args.Item.Node.NodeTypeID.Equals(MedianamikTypes.MedianamikSyndication))
                        {
                            var syndicatedNodeId = args.Item.Properties[MedianamikProperties.SyndicatedNode]
                                .GetValue<Guid?>();

                            if (syndicatedNodeId.HasValue)
                            {
                                node = NodeManager.GetNode(syndicatedNodeId.Value);
                            }
                        }
                        else
                        {
                            node = args.Item.Node;
                        }

                        var url = GetNewUrl(args.Item, node, GetOrderedParentNodes(node), args.Item.Culture);

                        if (!String.IsNullOrEmpty(url))
                            args.Item.Properties["url"].SetValue(url);
                    }
                }
            }
        }

        protected virtual List<Node> GetOrderedParentNodes(Node node)
        {
            var nodes = node.ParentNodes.Where(n => n.UseInChildUrls).ToList();
            nodes.Sort((n1, n2) => n1.Depth.CompareTo(n2.Depth));

            return nodes;
        }

        public virtual string Description
        {
            get { return "S'assure qu'une URL est présente sur un Noeud"; }
        }

        protected virtual WebSite GetDefaultWebSite(Node forNode)
        {
            return ConfigManager.GetAll<WebSite>().First();
        }

        protected virtual string GetNewUrl(NodeInstance instance, Node node,
            List<Node> orderedParentNodes, CultureInfo culture)
        {
            var doc = new XDocument(new XElement("urls"));

            var website = node.WebSite ?? GetDefaultWebSite(node);

            var urlDictionay = new ObjectFactory<IUrlDictionary>().Get();
            var url = urlDictionay.BuildUniqueRelativeUrlWithoutPrefixAndExtension(GetSegments(node, orderedParentNodes, culture), 
                instance.Culture, website);

            doc.Root.Add(new XElement("url"
                                      , new XAttribute("path", url)
                                      , new XAttribute("website", website.ID)));

            return doc.ToString();
        }

        protected virtual PathSegmentCollection GetSegments(Node node, List<Node> orderedParentNodes, CultureInfo culture)
        {
            var segments = new PathSegmentCollection();

            for (var i = 0; i < orderedParentNodes.Count; i++)
            {
                var parentNode = orderedParentNodes[i];
                parentNode.DefaultCulture = culture;
                segments.Add(i, new PathSegment(parentNode.DisplayName));
            }

            var currentNodeName = node.DisplayName;

            if (node.Instances.Exists(culture))
            {
                var temp = node.Instances[culture].Properties["Name"].Value;
                if (temp != null && temp.ToString().Length > 0)
                    currentNodeName = temp.ToString();
            }

            segments.Add(orderedParentNodes.Count, new PathSegment(currentNodeName));

            return segments;
        }
    }
}
